#include "VSCommand.h"
using namespace VSEngine2;
TCHAR VSCommand::msOptionNotFound[] = _T("option not found");
TCHAR VSCommand::msArgumentRequired[] = _T("option requires an argument");
TCHAR VSCommand::msArgumentOutOfRange[] = _T("argument out of range");

//----------------------------------------------------------------------------
VSCommand::VSCommand (int numArguments, TCHAR** arguments)
{
	mNumArguments = numArguments;

	if (mNumArguments > 0)
	{
		mArguments = VS_NEW TCHAR *[mNumArguments];
		for (int i = 0; i < mNumArguments; ++i)
		{
			mArguments[i] = arguments[i];
		}
	}
	else
	{
		mArguments = 0;
	}

	Initialize();
}
//----------------------------------------------------------------------------
VSCommand::VSCommand (TCHAR* commandLine)
{
	mNumArguments = 0;
	mArguments = 0;

	
	if (!commandLine)
	{
		return;
	}
	unsigned int uiLength = VSStrLen(commandLine);
	if (!uiLength)
	{
		return;
	}


	
	
	Argument* argList = 0;
	TCHAR * pNextToken = NULL;
	TCHAR* token = VSStrtok(commandLine, " ",&pNextToken);
	while (token)
	{
		mNumArguments++;

		Argument* current = VS_NEW Argument(token, argList);
		argList = current;

		token = VSStrtok(NULL, " ",&pNextToken);
	}

	mArguments = VS_NEW TCHAR *[mNumArguments];

	int i = mNumArguments - 1;
	while (argList)
	{
		mArguments[i] = argList->Item;

		Argument* save = argList;
		argList = argList->Next;
		VSMAC_DELETE(save);
		i--;
	}

	Initialize();
}
//----------------------------------------------------------------------------
VSCommand::~VSCommand ()
{

	VSMAC_DELETEA(mArguments);

}
//----------------------------------------------------------------------------
void VSCommand::Initialize ()
{

	mSmall = 0.0f;
	mLarge = 0.0f;
	mMinSet = false;
	mMaxSet = false;

	mLastError = 0;
}
//----------------------------------------------------------------------------
VSCommand& VSCommand::Min (VSREAL value)
{
	mSmall = value;
	mMinSet = true;
	return *this;
}
//----------------------------------------------------------------------------
VSCommand& VSCommand::Max (VSREAL value)
{
	mLarge = value;
	mMaxSet = true;
	return *this;
}
//----------------------------------------------------------------------------
int VSCommand::GetBoolean (const TCHAR* name)
{
	bool value = false;
	return GetBoolean(name, value);
}
//----------------------------------------------------------------------------
int VSCommand::GetBoolean (const TCHAR* name, bool& value)
{
	int matchFound = 0;
	value = false;
	for (int i = 1; i < mNumArguments; ++i)
	{
		TCHAR* tmp = mArguments[i];
		if (tmp[0] == ' ' && VSStrCmp(name, ++tmp) == 0)
		{
			matchFound = i;
			value = true;
			break;
		}
	}

	if (matchFound == 0)
	{
		mLastError = msOptionNotFound;
	}

	return matchFound;
}
//----------------------------------------------------------------------------
int VSCommand::GetInteger (const TCHAR* name, int& value)
{
	int matchFound = 0;
	for (int i = 1; i < mNumArguments; ++i)
	{
		TCHAR* tmp = mArguments[i];
		if (tmp[0] == ' ' && VSStrCmp(name, ++tmp) == 0)
		{
			// Get argument.
			tmp = mArguments[i + 1];
			if (tmp[0] == ' ' && !isdigit(tmp[1]))
			{
				mLastError = msArgumentRequired;
				return 0;
			}
			value = _tstoi(tmp);
			if ((mMinSet && value < mSmall)
				||  (mMaxSet && value > mLarge))
			{
				mLastError = msArgumentOutOfRange;
				return 0;
			}
			matchFound = i;
			break;
		}
	}

	mMinSet = false;
	mMaxSet = false;

	if (matchFound == 0)
	{
		mLastError = msOptionNotFound;
	}

	return matchFound;
}
//----------------------------------------------------------------------------
int VSCommand::GetReal (const TCHAR* name, VSREAL& value)
{
	int matchFound = 0;
	for (int i = 1; i < mNumArguments; ++i)
	{
		TCHAR* tmp = mArguments[i];
		if (tmp[0] == ' ' && VSStrCmp(name, ++tmp) == 0)
		{
			// Get argument.
			tmp = mArguments[i + 1];
			if ((tmp[0] == ' ' && !isdigit(tmp[1])))
			{
				mLastError = msArgumentRequired;
				return 0;
			}
			value = (VSREAL)_tstof(tmp);
			if ((mMinSet && value < mSmall)
				||  (mMaxSet && value > mLarge))
			{
				mLastError = msArgumentOutOfRange;
				return 0;
			}
			matchFound = i;
			break;
		}
	}

	mMinSet = false;
	mMaxSet = false;


	if (matchFound == 0)
	{
		mLastError = msOptionNotFound;
	}

	return matchFound;
}
//----------------------------------------------------------------------------
int VSCommand::GetString (const TCHAR* name, VSString & value)
{
	int matchFound = 0;
	for (int i = 1; i < mNumArguments; ++i)
	{
		TCHAR* tmp = mArguments[i];
		if (tmp[0] == ' ' && VSStrCmp(name, ++tmp) == 0)
		{
			// Get argument.
			tmp = mArguments[i + 1];
			if (tmp[0] == ' ')
			{
				mLastError = msArgumentRequired;
				return 0;
			}
			
			value = tmp;
			matchFound = i;
			break;
		}
	}

	if (matchFound == 0)
	{
		mLastError = msOptionNotFound;
	}

	return matchFound;
}
//----------------------------------------------------------------------------
const TCHAR* VSCommand::GetLastError ()
{
	return mLastError;
}